package com.zhangyj.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.JavaType;

import com.zhangyj.data.tables.BEnt;

/**
 * 一些常用的方法
 * 
 * @author 张有军
 * 
 */
public class Tools {
	private static Map<String, int[]> orderMap = new HashMap<String, int[]>();
	private static final String datePattern = "yyyy-MM-dd";
	private static final String dateTimePattern = "yyyy-MM-dd HH:mm:ss";
	public static final String VALIDATE_KEY = "_validate_key_";
	private static JsonFactory jf = new JsonFactory();
	private static ObjectMapper om = new ObjectMapper(jf);

	public static String object2jsonStr(Object o) throws JsonGenerationException, JsonMappingException, IOException {
		return om.writeValueAsString(o);
	}

	public static String object2jsonStr(/* List<Object> */Object list,String idField) throws JsonGenerationException, JsonMappingException, IOException {
		StringBuilder builder = new StringBuilder();
		builder.append("{identifier:\"").append(idField).append("\",items:");
		builder.append(om.writeValueAsString(list));
		builder.append("}");
		return builder.toString();
	}
	public static String object2jsonStr(/* List<Object> */Object list,String idField,int numRows) throws JsonGenerationException, JsonMappingException, IOException {
		StringBuilder builder = new StringBuilder();
		builder.append("{identifier:\"").append(idField).append("\",items:");
		builder.append(om.writeValueAsString(list));
		builder.append(",numRows:").append(numRows);
		builder.append("}");
		return builder.toString();
	}
	public static <T> T jsonStr2object(String jsonString, Class<T> obj) throws JsonGenerationException, JsonMappingException, IOException {
		return om.readValue(jsonString, obj);
	}

	public static <T> T jsonStr2object(String jsonString, JavaType type) throws JsonGenerationException, JsonMappingException, IOException {
		return om.readValue(jsonString, type);
	}

	public static Set<String> strSplitToSet(String str, String str2) {
		if (str == null)
			return null;
		StringTokenizer stk = new StringTokenizer(str, str2);
		Set<String> set = new HashSet<String>();
		while (stk.hasMoreTokens()) {
			set.add(stk.nextToken().trim());
		}
		return set;
	}

	/**
	 * 把字符串转化一个整数。如果转化过程中出现错误返回默认值。
	 * 
	 * @param str
	 *            要转化的字符串
	 * @param defaultVal
	 *            默认值
	 * @return
	 */
	public static int str2int(String str, int defaultVal) {
		if (str != null && str.length() > 0) {
			try {
				return Integer.valueOf(str);
			} catch (Exception e) {
				return defaultVal;
			}
		}
		return defaultVal;
	}

	/**
	 * @param str
	 * @return 返回一个字符串所占的字节长度
	 */
	public static int strByteLength(String str) {
		if (str == null) {
			return 0;
		}
		return str.getBytes().length;
	}

	/**
	 * @return 返回当前日期的字符串形式，长度是10；<br>
	 *         例如：2008-10-02
	 */
	public static String getDate() {
		SimpleDateFormat format = new SimpleDateFormat(datePattern);
		return format.format(new Date());
	}

	/**
	 * @return 返回当前日期时间的字符串形式，长度是19。<br>
	 *         例如：2008-10-02 12:12:12
	 */
	public static String getDateTime() {
		SimpleDateFormat format = new SimpleDateFormat(dateTimePattern);
		return format.format(new Date());
	}

	/**
	 * 
	 * @param date
	 * @return
	 * @throws ParseException
	 */
	public static Date str2Date(String date) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat(datePattern);
		return format.parse(date);
	}

	/**
	 * 
	 * @param dateTime
	 * @return
	 * @throws ParseException
	 */
	public static Date str2DateTime(String dateTime) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat(dateTimePattern);
		return format.parse(dateTime);
	}

	public static String base64Encode(String str) {
		return new String(Base64.encodeBase64(str.getBytes()));
	}

	public static String base64Decode(String str) {
		return new String(Base64.decodeBase64(str.getBytes()));
	}

	public static byte[] base64Encode(byte[] bytes) {
		return Base64.encodeBase64(bytes);
	}

	public static byte[] base64Decode(byte[] bytes) {
		return Base64.decodeBase64(bytes);
	}

	/**
	 * 使用Gzip算法压缩字节流
	 */
	public static byte[] gzipDeflate(byte[] bytes) throws java.io.IOException {
		java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
		java.io.DataOutputStream dos = new java.io.DataOutputStream(new java.util.zip.GZIPOutputStream(baos));
		dos.write(bytes);
		dos.close();
		return baos.toByteArray();
	}

	/**
	 * 使用Gzip算法解压缩字节流
	 */
	public static byte[] gzipInflate(byte[] bytes) throws java.io.IOException {
		java.util.zip.GZIPInputStream gis = new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(bytes));
		java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
		byte[] buf = new byte[4096];
		int len;
		while ((len = gis.read(buf)) >= 0) {
			baos.write(buf, 0, len);
		}
		gis.close();
		return baos.toByteArray();
	}

	/**
	 * 将字符串进行XML编码，即将一些xml中的保留字符进行转换，如& 转成&amp; < 转成 &lt;等
	 * 
	 * @param text
	 * @return
	 */
	public static StringBuilder xmlEcode(String text) {

		if (text == null)
			return new StringBuilder(0);
		int length = text.length();
		StringBuilder builder = new StringBuilder(length + length / 4);
		for (int i = 0; i < length; i++) {
			char c = text.charAt(i);
			switch (c) {
			case '<':
				builder.append("&lt;");
				break;
			case '>':
				builder.append("&gt;");
				break;
			case '\"':
				builder.append("&quot;");
				break;
			case '&':
				builder.append("&amp;");
				break;
			default:
				builder.append(c);
				break;
			}
		}
		return builder;
	}

	public static StringBuilder htmlEncode(String text) {
		if (text == null)
			return new StringBuilder(0);
		int length = text.length();
		StringBuilder builder = new StringBuilder(length + length / 4);
		for (int i = 0; i < length; i++) {
			char c = text.charAt(i);
			switch (c) {
			case '<':
				builder.append("&lt;");
				break;
			case '>':
				builder.append("&gt;");
				break;
			case '&':
				builder.append("&amp;");
				break;
			default:
				builder.append(c);
				break;
			}
		}
		return builder;
	}

	public static String translate(String text, String sourceCharsetName, String targetCharsetName) {
		if (text != null && text.length() > 0) {
			try {
				return new String(text.getBytes(sourceCharsetName), targetCharsetName);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return text;
	}

	public static String iso2utf8(String text) {
		return translate(text, "ISO8859-1", "UTF-8");
	}

	public static String getParameter(HttpServletRequest request, String param, String defaultVal) {
		String result = request.getParameter(param);
		if (result == null)
			return defaultVal;

		if (result.length() == 0)
			return result;

		String encode = request.getCharacterEncoding();
		if (encode == null) {
			return iso2utf8(result);
		} else if (encode.equalsIgnoreCase("UTF-8")) {
			return result;
		} else {
			return translate(result, encode, "UTF-8");
		}
	}

	public static String getParameter(HttpServletRequest request, String param) {
		return getParameter(request, param, "");
	}

	public static int getIntParameter(HttpServletRequest request, String param) {
		return getIntParameter(request, param, 0);
	}

	public static int getIntParameter(HttpServletRequest request, String param, int defaultVal) {
		try {
			String val = getParameter(request, param, "");
			if (val.length() > 0) {
				return Integer.parseInt(val);
			}
		} catch (Exception e) {

		}
		return defaultVal;
	}

	public static Object getAttribute(HttpServletRequest request, String param) {
		return getAttribute(request, param, "");
	}

	public static Object getAttribute(HttpServletRequest request, String param, Object defaultVal) {
		Object obj = request.getAttribute(param);
		if (obj == null) {
			obj = defaultVal;
		}
		return obj;
	}

	public static String gzipDeflateBase64Encode(String text) throws IOException {
		String e = new String(base64Encode(gzipDeflate(text.getBytes())));
		e = e.substring(13);
		return e;
	}

	public static String Base64DecodeGzipInflate(String text) throws IOException {
		return new String(gzipInflate(base64Decode(("H4sIAAAAAAAAA" + text).getBytes())));
	}

	public static String getValidateCode() {
		long code = Math.round(Math.random() * 10000);
		String strCode = String.valueOf(code);
		for (int i = strCode.length(); i < 4; i++)
			strCode += "0";
		return strCode;

	}

	public static String builderJSONString(String val) {
		if (val == null) {
			return "";
		}
		int index = 0;
		if ((index = val.indexOf('\"', index)) != -1) {
			return val.replaceAll("\"", "\\\"");
		} else {
			return val;
		}
	}

	public static String builderSelect(String[][] arr, String name, String value) {
		return builderSelect(arr, name, value, false);
	}

	public static String builderSelect(int start, int end, String name, int value, String event) {
		String[][] arr = new String[end - start + 1][];
		for (int i = start; i <= end; i++) {
			arr[i] = new String[] { i + "", i + "" };
		}
		return builderSelect(arr, name, value + "", event, false);
	}

	public static String builderSelect(String[][] arr, String name, String value, boolean readonly) {
		StringBuilder buf = new StringBuilder();
		if (readonly) {
			for (int i = 0; i < arr.length; i++) {
				String[] vals = arr[i];
				if (vals[0].equals(value)) {
					return htmlEncode(vals[1]).toString();
				}
			}
		} else {
			buf.append("<select name=\"").append(name).append("\" >");
			for (int i = 0; i < arr.length; i++) {
				String[] vals = arr[i];
				buf.append("<option value=\"").append(htmlEncode(vals[0])).append("\" ");
				if (vals[0].equals(value)) {
					buf.append("selected=\"selected\"");
				}
				buf.append(" > ").append(htmlEncode(vals[1])).append("</option>");
			}
			buf.append("</select>");
		}
		return buf.toString();
	}

	public static String builderSelect(String[][] arr, String name, String value, String event, boolean readonly) {
		StringBuilder buf = new StringBuilder();
		if (readonly) {
			for (int i = 0; i < arr.length; i++) {
				String[] vals = arr[i];
				if (vals[0].equals(value)) {
					return htmlEncode(vals[1]).toString();
				}
			}
		} else {
			buf.append("<select style=\"width:100%\" name=\"").append(name).append("\" ");
			if (event != null) {
				buf.append(event);
			}
			buf.append(">");
			for (int i = 0; i < arr.length; i++) {
				String[] vals = arr[i];
				buf.append("<option value=\"").append(htmlEncode(vals[0])).append("\" ");
				if (vals[0].equals(value)) {
					buf.append("selected=\"selected\"");
				}
				buf.append(" > ").append(htmlEncode(vals[1])).append("</option>");
			}
			buf.append("<select>");
		}
		return buf.toString();
	}

	public static void fullBean(Object bean, HttpServletRequest request) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		Enumeration<?> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = (String) names.nextElement();
			map.put(name, request.getParameter(name));
		}
		BeanUtils.populate(bean, map);
	}

	public static String builderUrl(HttpServletRequest request, String file) {
		return file;
	}

	public static String builderUrl(HttpServletRequest request, String file, Map<String, String> param) {
		StringBuilder path = new StringBuilder();
		path.append(file);
		if (param != null) {
			if (file.indexOf("?") == -1) {
				path.append("?");
			}
			boolean add = false;
			char c = path.charAt(path.length() - 1);
			if (c != '?' && c != '&') {
				add = true;
			}
			for (Iterator<Entry<String, String>> iter = param.entrySet().iterator(); iter.hasNext();) {
				if (add) {
					path.append("&");
				} else {
					add = true;
				}
				Entry<String, String> entry = iter.next();
				path.append(entry.getKey()).append("=").append(entry.getValue());
			}
		}
		return path.toString();
	}

	public static void formSuccess(Writer writer, String msg, Object obj) throws IOException {
		writer.append("{\"success\":true");
		if (msg != null && msg.length() > 0) {
			writer.append(",\"msg\":\"").append(builderJSONString(msg)).append("\"");
		}
		if (obj != null) {
			writer.append(",\"result\":").append(object2jsonStr(obj));
		}
		writer.append("}");
	}

	public static void formFail(Writer writer, String msg, Object obj) throws IOException {
		writer.append("{\"success\":false");
		if (msg != null && msg.length() > 0) {
			writer.append(",\"msg\":\"").append(builderJSONString(msg)).append("\"");
		}
		if (obj != null) {
			writer.append(",\"result\":").append(object2jsonStr(obj));
		}
		writer.append("}");
	}

	/**
	 * 业务标识 + 日期到分钟 + 1到10万的序列号
	 * 
	 * @param prefix
	 *            业务标识
	 * @return
	 */
	public static synchronized String getBillCode(int entid, String prefix) {
		String key = entid + prefix;
		Calendar cal = Calendar.getInstance();
		int[] obj = orderMap.get(key);
		if (obj == null) {
			obj = new int[] { cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), 1 };
			orderMap.put(key, obj);
		} else if (obj[0] == cal.get(Calendar.YEAR) && obj[1] == cal.get(Calendar.MONTH) && obj[2] == cal.get(Calendar.DAY_OF_MONTH) && obj[3] == cal.get(Calendar.HOUR_OF_DAY)
				&& obj[4] == cal.get(Calendar.MINUTE)) {
			obj[5]++;
		} else {
			obj[0] = cal.get(Calendar.YEAR);
			obj[1] = cal.get(Calendar.MONTH);
			obj[2] = cal.get(Calendar.DAY_OF_MONTH);
			obj[3] = cal.get(Calendar.HOUR_OF_DAY);
			obj[4] = cal.get(Calendar.MINUTE);
			obj[5] = 1;
		}
		StringBuilder builder = new StringBuilder();
		builder.append(prefix);
		// 年
		builder.append(obj[0]);
		// 月
		if (obj[1] < 9) {
			builder.append("0");
		}
		builder.append(obj[1] + 1);
		// 日
		if (obj[2] < 10) {
			builder.append("0");
		}
		builder.append(obj[2]);

		// 小时
		if (obj[3] < 10) {
			builder.append("0");
		}
		builder.append(obj[3]);

		// 分钟
		if (obj[4] < 10) {
			builder.append("0");
		}
		builder.append(obj[4]);

		// 机器码
		builder.append("1");
		String num = obj[5] + "";
		for (int i = 0; i <= 5 - num.length(); i++) {
			builder.append("0");
		}
		builder.append(num);

		return builder.toString();
	}

	public static void main(String arg[]) {
		try {
			System.out.println(getBillCode(1, "CGD"));
			System.out.println(getBillCode(1, "CGD"));
			System.out.println(getBillCode(1, "CGD"));
			// double rd = Math.random();
			BEnt a = new BEnt();
			List<BEnt> list = new ArrayList<BEnt>();
			
			list.add(a);

			
			System.out.println(object2jsonStr(list, "entId"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
